Una adquisición muy interesante en el mundo Arduino, es la placa Esplora. Esta placa es quizás la mejor para aprender la programación de la placa, ya que integra casi todos los elementos que utilizaríamos con la placa Arduino normal.

Entre ellos se encuentran:

  • Joystick
  • 4 Botones de dirección
  • Potenciometro lineal
  • Micrófono
  • Zumbador
  • LED RGB
  • Sensor de Luz
  • Acelerómetro
  • Sensor de temperatura

Por otra parte, esta placa tiene una serie de pines a los que se le puede conectar una pantalla TFT a color (18-bit) de 128 x 160 (1,8 pulgadas)  – ST7735R.

TFTEsplora

Todo esto es muy útil, pero nos centraremos en el Joystick. Y es que el Joystick es una pieza muy interesante para utilizar esta placa como si de una consola se tratara y es a ello a lo que nos vamos a referir.

Nuestro objetivo principalmente va a ser interactuar dentro de la pantalla con los botones y el joystick, pero vamos a comprobar que no es tan sencillo como parece, debido a algunos aspectos.

Vamos a realizar una primera lectura de los valores que podemos leer con el Joystick, para ver qué es lo que ocurre.


#include <Esplora.h>



void setup() {

  Serial.begin(9600);
}

void loop() {

  Serial.print(" Value X ");
  Serial.println(Esplora.readJoystickX());
  Serial.print(" Value Y ");
  Serial.println(Esplora.readJoystickY());
  Serial.println();
}

 

 

SerialEsploraJoystickSerialEsploraJoystick


 

Como se puede observar, si no desplazamos el joystick, existe un valor que altera las medidas y por muy pequeño que sea, deberíamos ser capaces de eliminar ese estado. Ya que si tuvieramos un personaje que se mueve por la pantalla, el mero hecho de tenerlo quieto, provocaría que el personaje se moviera hacia algún lado. Otra cuestión a tener en cuenta, es que el error varía y no es estable.

Por otra parte, vemos cómo se asocian los valores de el joystick, que nos proporciona un valor máximo de 512 y que sus movimientos en los ejes están invertidos.

Para arreglar este caso hemos de aplicar un filtro en el que, especificando un valor superior e inferior para cada uno de los ejes, el valor se mantenga a cero y que no afecte a las lecturas. En la gráfica se puede ver este comportamiento.

 

OffsetLinealAvoidYa que tenemos un rango amplio de 512 y los valores de error son bajos; en torno a -6 y 6, lo que vamos a hacer será cubrir este error a 10 y -10 para que cualquier lectura de los ejes se mantenga a cero y eliminar el offset.


#include <Esplora.h>

int X, Y;
int X_minOffset, X_maxOffset, Y_minOffset, Y_maxOffset;
int X_limit, Y_limit;
void setup() {
  Serial.begin(9600);
  X_minOffset = -10;
  X_maxOffset = 10;
  Y_minOffset = -10;
  Y_maxOffset = 10;

  X_limit = 100;
  Y_limit = 100;
}

void loop() {
  X = Esplora.readJoystickX();
  Y = Esplora.readJoystickY();
  
  int Xvalue = 0;
  int Yvalue = 0;
  
  if(X > X_maxOffset || X < X_minOffset ){
     Xvalue = map(X,-512,512,-X_limit,X_limit);
  }

  if(Y > Y_maxOffset || Y < Y_minOffset ){
     Yvalue = map(Y,-512,512,-Y_limit,Y_limit);
  }
  Serial.print(" Value X ");
  Serial.println(Xvalue);
  Serial.print(" Value Y ");
  Serial.println(Yvalue);
  Serial.println();
}

 

 

Esto nos resuelve el problema. Podemos ver además que utilizamos una función map, para relacionar los valores de los límites del joystick para aplicarlos a una escala que nos interese.

Ahora vamos a realizar algo un poco más complicado con la pantalla. Para conectar la pantalla, solo necesitaremos descargarnos unas librerías para realizar el ejercicio, incluirlas dentro de Arduino y empezar a jugar.

Las librerías para la pantalla ST7735 son las siguientes.

 


#include <Adafruit_ST7735.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Esplora.h>  // use Esplora library function

// SPI pins for Esplora (Arduino Leonardo style numbering)
#define mosi 16
#define miso 14
#define sclk 15
#define cs    7  // Esplora uses display chip select on D7
#define dc    0  // Esplora uses LCD DC on D0
#define rst   1 // Esplora uses display reset on D1

Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst);  // define tft display (use Adafruit library) hw (if you add osi and sclk it will slow too much)

int X, Y;
int playerPaddleX,playerPaddleY;   // Player Paddle Position
int width,height,center;

//Multitasking Non Blocking graphics
long previousMillis = 0;  //Reference Millis
long frame_time;          //Frames per second Measurement

//Parameters increasing joystick moves. Set incremental move per frame
int X_limit,Y_limit;

int X_minOffset = -10;
int X_maxOffset = 10;

int Y_minOffset = -10;
int Y_maxOffset = 10;

void setup() {

  Serial.begin(9600);
  tft.initR(INITR_GREENTAB);       // Initialize Adafruit display - use GREENTAB if you have such display

  uint16_t bckg=0x0000;
  tft.fillScreen(bckg);  // clear display
  tft.setRotation(1);            // landscape (as on Esplora)

  width=160;
  height=128;

  playerPaddleX=width/2;    // set paddles in the center of the display
  playerPaddleY=height/2;
  
  frame_time=20;
  
  //Valor entre pixel y pixel en cada una de las coordenadas
  X_limit=4;
  Y_limit=4;
}

void loop() {
  
  //Time Millis() for graphics frame measurement
  unsigned long currentMillis = millis();

  int Xvalue = 0;
  int Yvalue = 0;
  
  if (playerPaddleY <=1)  // This is so the paddle does not move off the screen on the bottom side of the screen
    playerPaddleY=2;
  if (playerPaddleY >=height) // This is so the paddle does not move off the screen on the top side of the screen
    playerPaddleY=height-1;
    
  if (playerPaddleX <=1)  // This is so the paddle does not move off the screen on the bottom side of the screen
    playerPaddleX=2;
  if (playerPaddleX >=width) // This is so the paddle does not move off the screen on the top side of the screen
    playerPaddleX=width-1;
    
  if(currentMillis - previousMillis > frame_time) {
      previousMillis = currentMillis;
        
      Y = Esplora.readJoystickY();
  
      if(Y > Y_maxOffset || Y < Y_minOffset ){
         Yvalue = map(Y,-512,512,-Y_limit,Y_limit);
         playerPaddleY=playerPaddleY+Yvalue;
      }
      
      X = Esplora.readJoystickX();
      
      if(X > X_maxOffset || X < X_minOffset){
        Xvalue = map(X,-512,512,-X_limit,X_limit);
        playerPaddleX=playerPaddleX-Xvalue;
      }
  
      tft.drawPixel(playerPaddleX, playerPaddleY,0xFFFF);   
  }
}


En el siguiente video podemos ver qué es lo que podemos hacer con este telesketch Arduino 🙂

 

Algunos aspectos a tener en cuenta son:

  • Para iniciar la pantalla TFT, hay que mirar cuál hemos comprado y como se puede ver en el video, la mia tiene un plástico para recubrirla con una pestaña verde. Es por ello, que hay que iniciarla con INITR_GREENTAB de los 3 disponibles. (INITR_GREENTAB, INITR_REDTAB, INITR_BLACKTAB)
  • La rotación de la pantalla está a 1 para poder verla adecuadamente a la placa Arduino Esplora.
  • La pantalla TFT se conecta por SPI, por lo que es necesario definir los pines de cs, dc y rst; tal y como se explica en el código.
  • Hay un control de tiempo determinado por la función millis. Esto nos permite evitar retrasos dentro de nuestros desarrollos gráficos y establecer unos frames por segundo para realizar las pintadas y no crear bloqueos.
  • También hemos creado un control para evitar los márgenes y que nuestra linea no se vaya más allá de la pantalla.
  • La librería Adafruit_GFX es una extensión para hacer cosas más chulas.

 

Existe un aspecto más a investigar y es el vector creado por el joystick a la hora de moverlo y que si lo estudiamos un poco, nos proporciona una mayor precisión en nuestros dibujos con el Joystick Arduino.

 

Por ejemplo; si especificamos X_limit e Y_limit, los dos a un valor de 1; podremos comprobar que la linea viaja de forma retilinea o con ángulos de 45 grados. Esto se debe a que solo hay 9 estados posibles en esa lectura.

XYAction
00No se mueve a ningún lado
01Hacia abajo
10Hacia la izquierda
-10Hacia la derecha
0-1Hacia Arriba
11Esquina inferior izquierdo (Ángulo de 45º hacia abajo a la izquierda)
-1 -1 Esquina superior derecha (Ángulo de 45º hacia arriba a la derecha)
1-1Esquina superior izquierda (Ángulo de 45º hacia arriba a la izquierda)
-11Esquina inferior derecha (Ángulo de 45º hacia abajo a la derecha)

Este hecho nos limita, y es por ello que es mejor definir otros valores superiores para los valores X_limit e Y_limit y poder aumentar la sensibilidad de nuestros movimientos.